package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import model.BoardModel;
import control.Kamisado;
import control.Pos;

public class BoardView extends JFrame {

	private static final long serialVersionUID = 1L;
	private Pos clickPos;
	private FieldView[][] fields;
	private JFrame frame;
	private JPanel gameField;
	private Kamisado kamisado;
	private JList<String> list;

	private DefaultListModel<String> log;

	private BoardModel model;

	private JLabel statusLabel;

	public BoardView(BoardModel m, Kamisado k) {
		kamisado = k;
		model = m;
		frame = this;
		gameField = new JPanel();
		makeFrame();
	}

	public void addLog(String s) {
		log.addElement(s);
		list.ensureIndexIsVisible(log.getSize() - 1);
		repaint();
	}

	private void addResizer() {
		frame.addComponentListener(new ComponentListener() {

			@Override
			public void componentHidden(ComponentEvent e) {

			}

			@Override
			public void componentMoved(ComponentEvent e) {

			}

			@Override
			public void componentResized(ComponentEvent e) {
				gameFieldResize();
			}

			@Override
			public void componentShown(ComponentEvent e) {
			}
		});

		frame.addWindowStateListener(new WindowStateListener() {

			@Override
			public void windowStateChanged(WindowEvent e) {
				gameFieldResize();
			}
		});

		frame.addWindowListener(new WindowListener() {

			@Override
			public void windowActivated(WindowEvent e) {
			}

			@Override
			public void windowClosed(WindowEvent e) {
			}

			@Override
			public void windowClosing(WindowEvent e) {
			}

			@Override
			public void windowDeactivated(WindowEvent e) {
			}

			@Override
			public void windowDeiconified(WindowEvent e) {
			}

			@Override
			public void windowIconified(WindowEvent e) {
			}

			@Override
			public void windowOpened(WindowEvent e) {
			}
		});

	}

	private void gameFieldResize() {
		int actualHeight = gameField.getParent().getHeight();
		int actualWidth = gameField.getParent().getWidth();
		int min = 0;

		if (actualHeight < actualWidth)
			min = actualHeight;
		else
			min = actualWidth;

		gameField.setPreferredSize(new Dimension(min, min));
	}

	public Pos getNextMove() {
		return clickPos;
	}

	private void makeContent() {
		frame.getContentPane().setLayout(new BorderLayout());
		makeGameField();
		makeStatusLabel();
		makeLog();
	}

	private void makeFrame() {
		frame.setTitle("Kamisado Beta");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// frame.setSize(1000, 760);
		// frame.setLocationRelativeTo(null);

		makeMenu();
		makeContent();
		// addResizer();

		frame.setVisible(true);
		frame.setResizable(false);
		frame.pack();
		frame.setLocationRelativeTo(null);
		// frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
	}

	private void makeGameField() {

		int size = 8;

		GridBagLayout layout = new GridBagLayout();

		GridBagConstraints constraints = new GridBagConstraints();

		constraints.fill = GridBagConstraints.BOTH;
		constraints.anchor = GridBagConstraints.CENTER;

		gameField.setLayout(layout);
		gameField.setBackground(Color.WHITE);

		fields = new FieldView[size][size];

		for (int i = 0; i < size + 2; i++) {

			for (int j = 0; j < size + 2; j++) {

				if (i == 0 | i == size + 1) {

					if (j != 0 & j != size + 1) {

						constraints.gridx = j;
						constraints.gridy = i;
						constraints.ipadx = 0;
						constraints.ipady = 10;

						JLabel label = new JLabel("" + (char) (64 + j));
						label.setHorizontalAlignment(JLabel.CENTER);

						gameField.add(label, constraints);

					}

				} else if (j == 0 | j == size + 1) {

					if (i != 0 & i != size + 1) {

						constraints.gridx = j;
						constraints.gridy = i;
						constraints.ipadx = 10;
						constraints.ipady = 0;

						JLabel label = new JLabel("" + (9 - i));
						label.setHorizontalAlignment(JLabel.CENTER);

						gameField.add(label, constraints);

					}

				} else {

					constraints.gridx = j;
					constraints.gridy = i;
					constraints.ipadx = 0;
					constraints.ipady = 0;

					fields[i - 1][j - 1] = new FieldView(i - 1, j - 1, model,
							kamisado, this);

					gameField.add(fields[i - 1][j - 1], constraints);

				}

			}

		}

		// TODO implement better status field
		// JTextField tf = new JTextField("rofl");
		// frame.getContentPane().add(tf, BorderLayout.CENTER);

		frame.getContentPane().add(gameField, BorderLayout.CENTER);
	}

	private void makeLog() {
		log = new DefaultListModel<>();
		log.addElement("Game Log");
		log.addElement("-");

		list = new JList<String>();
		list.setModel(log);

		list.setBackground(Color.BLACK);
		list.setForeground(Color.GREEN);

		JScrollPane scrollArea = new JScrollPane(list);
		scrollArea.setPreferredSize(new Dimension(200, 100));

		frame.getContentPane().add(scrollArea, BorderLayout.EAST);
	}

	private void makeMenu() {
		JMenuBar bar = new JMenuBar();
		JMenu menu = new JMenu("File");

		// new game human vs human
		JMenuItem newGameHvH = new JMenuItem("New Game (Human vs Human)");
		newGameHvH.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				addLog("- - - - - - - -");
				kamisado.newGameHvH();
			}
		});
		menu.add(newGameHvH);

		// new game human vs computer
		JMenuItem newGameHvC = new JMenuItem("New Game (Human vs Computer)");
		newGameHvC.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				addLog("- - - - - - - -");
				kamisado.newGameHvC();
			}
		});
		menu.add(newGameHvC);

		// new game computer vs computer
		JMenuItem newGameCvC = new JMenuItem("New Game (Computer vs Computer)");
		newGameCvC.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				addLog("- - - - - - - -");
				kamisado.newGameCvC();
			}
		});
		menu.add(newGameCvC);

		JMenuItem exit = new JMenuItem("Exit");
		exit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		menu.add(exit);

		bar.add(menu);
		frame.setJMenuBar(bar);
	}

	private void makeStatusLabel() {
		statusLabel = new JLabel("Welcome to Kamisado.");
		JPanel status = new JPanel();
		status.add(statusLabel);
		frame.getContentPane().add(status, BorderLayout.SOUTH);
	}

	private void repaintFields() {
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if (model.getFigure(i, j) != null
						&& model.getFigure(i, j).isMarked())
					fields[i][j].setMarked(true);
				else
					fields[i][j].setMarked(false);
				fields[i][j].repaint();
			}
		}
	}

	public void setClickPos(int posX, int posY) {

		clickPos = new Pos(posX, posY);

		kamisado.clicked(clickPos);

	}

	public void updateStatus() {
		statusLabel.setText(model.getStatus());
		repaintFields();
		repaint();
	}

}
